<!DOCTYPE html>





<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/favicon.ico?v=7.4.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.ico?v=7.4.0">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.ico?v=7.4.0">
  <link rel="mask-icon" href="/images/logo.svg?v=7.4.0" color="#222">

<link rel="stylesheet" href="/css/main.css?v=7.4.0">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '7.4.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false,"dimmer":false},
    copycode: {"enable":false,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":false},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: 'search.json',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: '复制',
      copy_success: '复制成功',
      copy_failure: '复制失败'
    },
    sidebarPadding: 40
  };
</script>

  <meta name="description" content="1. location指令根据请求的URI来设置具体规则, URI是url中除去协议和域名及参数后, 剩下的部分. 比如请求的url为: http://www.liuvv.com/test/index.php?page=1, 则uri 为 /test/index.php 1.1 location匹配uri的规则:1location [ = | ~ | ~* | ^~ ] uri &amp;#123; .">
<meta name="keywords" content="linux,nginx">
<meta property="og:type" content="article">
<meta property="og:title" content="nginx的location用法和rewrite规则">
<meta property="og:url" content="https://unix2dos.github.io/p/51e59d76.html">
<meta property="og:site_name" content="Levon&#39;s Blog">
<meta property="og:description" content="1. location指令根据请求的URI来设置具体规则, URI是url中除去协议和域名及参数后, 剩下的部分. 比如请求的url为: http://www.liuvv.com/test/index.php?page=1, 则uri 为 /test/index.php 1.1 location匹配uri的规则:1location [ = | ~ | ~* | ^~ ] uri &amp;#123; .">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2019-09-27T15:36:51.176Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="nginx的location用法和rewrite规则">
<meta name="twitter:description" content="1. location指令根据请求的URI来设置具体规则, URI是url中除去协议和域名及参数后, 剩下的部分. 比如请求的url为: http://www.liuvv.com/test/index.php?page=1, 则uri 为 /test/index.php 1.1 location匹配uri的规则:1location [ = | ~ | ~* | ^~ ] uri &amp;#123; .">
  <link rel="canonical" href="https://unix2dos.github.io/p/51e59d76">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>nginx的location用法和rewrite规则 | Levon's Blog</title>
  








  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">
  <div class="container use-motion">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Levon's Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <h1 class="site-subtitle" itemprop="description">微信:  L6241425</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
      
      
      
        
        <li class="menu-item menu-item-home">
      
    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-archives">
      
    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>时光</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-categories">
      
    

    <a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-tags">
      
    

    <a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>

  </li>
      <li class="menu-item menu-item-search">
        <a href="javascript:;" class="popup-trigger">
        
          <i class="menu-item-icon fa fa-search fa-fw"></i> <br>搜索</a>
      </li>
    
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocorrect="off" autocapitalize="none"
           placeholder="搜索..." spellcheck="false"
           type="text" id="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result"></div>

</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
            

          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
      <article itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block post">
    <link itemprop="mainEntityOfPage" href="https://unix2dos.github.io/p/51e59d76.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Levon">
      <meta itemprop="description" content="Never Give Up">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Levon's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">nginx的location用法和rewrite规则

          
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              
                
              

              <time title="创建时间：2019-07-11 23:54:46" itemprop="dateCreated datePublished" datetime="2019-07-11T23:54:46+08:00">2019-07-11</time>
            </span>
          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2019-09-27 23:36:51" itemprop="dateModified" datetime="2019-09-27T23:36:51+08:00">2019-09-27</time>
              </span>
            
          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/2-linux系统/" itemprop="url" rel="index"><span itemprop="name">2-linux系统</span></a></span>

                
                
                  ，
                
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/2-linux系统/nginx/" itemprop="url" rel="index"><span itemprop="name">nginx</span></a></span>

                
                
              
            </span>
          

          
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
        
      
      <span class="post-meta-item-text">Disqus：</span>
    
    <a title="disqus" href="/p/51e59d76.html#comments" itemprop="discussionUrl"><span class="post-comments-count disqus-comment-count" data-disqus-identifier="p/51e59d76.html" itemprop="commentCount"></span></a>
  </span>
  
  
          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
              
                <span class="post-meta-item-text">本文字数：</span>
              
              <span>12k</span>
            </span>
          
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
              
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              
              <span>11 分钟</span>
            </span>
          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h3 id="1-location指令"><a href="#1-location指令" class="headerlink" title="1. location指令"></a>1. location指令</h3><p>根据请求的URI来设置具体规则, URI是url中除去协议和域名及参数后, 剩下的部分.</p>
<p>比如请求的url为: <a href="http://www.liuvv.com/test/index.php?page=1" target="_blank" rel="noopener">http://www.liuvv.com/test/index.php?page=1</a>, 则uri 为 <code>/test/index.php</code></p>
<h5 id="1-1-location匹配uri的规则"><a href="#1-1-location匹配uri的规则" class="headerlink" title="1.1 location匹配uri的规则:"></a>1.1 location匹配uri的规则:</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">location [ = | ~ | ~* | ^~ ] uri &#123; ... &#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><code>=</code>  精确匹配, uri要完全一样</li>
<li><code>^~</code>  这个是以某个开头, 不是正则匹配</li>
<li><code>~</code>  区分大小写正则匹配</li>
<li><code>~*</code> 不区分大小写正则匹配</li>
</ul>
<a id="more"></a>

<h5 id="1-2-location匹配uri的优先级"><a href="#1-2-location匹配uri的优先级" class="headerlink" title="1.2 location匹配uri的优先级:"></a>1.2 location匹配uri的优先级:</h5><ol>
<li><p>首先先检查使用前缀字符定义的location，选择最长匹配的项并记录下来。</p>
</li>
<li><p>如果找到了精确匹配的location，也就是使用了<code>=</code>修饰符的location，结束查找，使用它的配置。</p>
</li>
<li><p>如果<code>^~</code>修饰符先匹配到最长的前缀字符串, 则不检查正则。</p>
</li>
<li><p>然后按顺序查找使用正则定义的location，如果匹配则停止查找，使用它定义的配置。</p>
</li>
<li><p>如果没有匹配的正则location，则使用前面记录的最长匹配前缀字符location。</p>
</li>
</ol>
<blockquote>
<p>基于以上的匹配过程，我们可以得到以下启示：</p>
</blockquote>
<ol>
<li>使用正则定义的location在配置文件中出现的顺序很重要。因为找到第一个匹配的正则后，查找就停止了，后面定义的正则就是再匹配也没有机会了。</li>
<li>使用精确匹配可以提高查找的速度。例如经常请求<code>/</code>的话，可以使用<code>=</code>来定义location。</li>
<li>优先级 <code>=</code>  &gt;  <code>^~</code>  &gt;  正则</li>
</ol>
<h5 id="1-3-location-测试"><a href="#1-3-location-测试" class="headerlink" title="1.3 location 测试"></a>1.3 location 测试</h5><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span> = / &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则A\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span> = /login &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则B\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span><span class="regexp"> ^~</span> /static/ &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则C\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span><span class="regexp"> ^~</span> /static/files &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则D\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span> <span class="regexp">~ \.(gif|jpg|png|js|css)$</span> &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则E\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span> <span class="regexp">~* \.PNG$</span> &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则F\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span> /img &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则G\n"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="attribute">location</span> / &#123;</span><br><span class="line">  <span class="attribute">return</span> <span class="number">502</span> <span class="string">"规则H\n"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试结果:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">levonfly@hk:~$ curl test.liuvv.com <span class="comment"># 因为是=</span></span><br><span class="line">规则A</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/ <span class="comment"># 因为是=</span></span><br><span class="line">规则A</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/login <span class="comment"># 因为是=</span></span><br><span class="line">规则B</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/login/ <span class="comment"># 多了/, 参考下面3.5</span></span><br><span class="line">规则H</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/abc</span><br><span class="line">规则H</span><br><span class="line"></span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/static/a.html </span><br><span class="line">规则C</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/static/files/a.html <span class="comment"># 更加精准</span></span><br><span class="line">规则D</span><br><span class="line"></span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/a.png <span class="comment"># 正则精准</span></span><br><span class="line">规则E</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/a.PNG <span class="comment"># 正则精准</span></span><br><span class="line">规则F</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/static/a.png <span class="comment"># ^~ 优先级更高</span></span><br><span class="line">规则C</span><br><span class="line"></span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/img/a.gif <span class="comment">#正则匹配优先</span></span><br><span class="line">规则E</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/img/a.tiff</span><br><span class="line">规则G</span><br><span class="line">levonfly@hk:~$ curl test.liuvv.com/abc/123/haha <span class="comment">#什么都匹配不到, 就到H</span></span><br><span class="line">规则H</span><br></pre></td></tr></table></figure>

<h5 id="1-4-location-name的用法"><a href="#1-4-location-name的用法" class="headerlink" title="1.4 location @name的用法"></a>1.4 location @name的用法</h5><p>@用来定义一个命名location。主要用于内部重定向，不能用来处理正常的请求。其用法如下：</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span> / &#123;</span><br><span class="line">    <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ <span class="variable">@custom</span></span><br><span class="line">&#125;</span><br><span class="line">location <span class="variable">@custom</span> &#123;</span><br><span class="line">    <span class="comment"># ...do something</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上例中，当尝试访问url找不到对应的文件就重定向到我们自定义的命名location（此处为custom）。</p>
<p>值得注意的是，命名location中不能再嵌套其它的命名location。</p>
<h5 id="1-5-root和alias的区别"><a href="#1-5-root和alias的区别" class="headerlink" title="1.5 root和alias的区别"></a>1.5 root和alias的区别</h5><p>nginx指定文件路径有两种方式root和alias.</p>
<ul>
<li>root</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[root]</span><br><span class="line">语法：root path</span><br><span class="line">默认值：root html</span><br><span class="line">配置段：http、server、location、if</span><br></pre></td></tr></table></figure>

<p>例如:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span><span class="regexp"> ^~</span> /t/ &#123; </span><br><span class="line">     <span class="attribute">root</span> /www/root/html/;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果一个请求的URI是/t/a.html时，web服务器将会返回服务器上的/www/root/html/t/a.html的文件。</p>
<ul>
<li>alias</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[alias]</span><br><span class="line">语法：alias path</span><br><span class="line">配置段：location</span><br></pre></td></tr></table></figure>

<p>例如:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span><span class="regexp"> ^~</span> /t/ &#123; <span class="comment"># 特殊的规则是, alias必须以"/" 结束</span></span><br><span class="line"> <span class="attribute">alias</span> /www/root/html/new_t/;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果一个请求的URI是/t/a.html时，web服务器将会返回服务器上的/www/root/html/new_t/a.html的文件。注意这里是new_t，因为alias会把location后面配置的路径丢弃掉，把当前匹配到的目录指向到指定的目录。</p>
<h5 id="1-6-nginx显示目录结构"><a href="#1-6-nginx显示目录结构" class="headerlink" title="1.6 nginx显示目录结构"></a>1.6 nginx显示目录结构</h5><p>nginx默认是不允许列出整个目录的。如需此功能, 在server或location 段里添加上autoindex on;</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">autoindex_exact_size</span> <span class="literal">off</span>;</span><br><span class="line">默认为on，显示出文件的确切大小，单位是bytes。</span><br><span class="line">改为off后，显示出文件的大概大小，单位是kB或者MB或者GB</span><br><span class="line"></span><br><span class="line"><span class="attribute">autoindex_localtime</span> <span class="literal">on</span>;</span><br><span class="line">默认为off，显示的文件时间为GMT时间。</span><br><span class="line">改为on后，显示的文件时间为文件的服务器时间</span><br></pre></td></tr></table></figure>

<p>可以下面的例子:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span><span class="regexp"> ^~</span> <span class="string">"/upload-preview"</span> &#123;</span><br><span class="line">		<span class="attribute">alias</span> /tmp/cistern/;</span><br><span class="line">		<span class="attribute">autoindex</span> <span class="literal">on</span>;</span><br><span class="line">		<span class="attribute">autoindex_localtime</span> <span class="literal">on</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="1-7-URL尾部的-需不需要"><a href="#1-7-URL尾部的-需不需要" class="headerlink" title="1.7 URL尾部的/需不需要"></a>1.7 URL尾部的<code>/</code>需不需要</h5><p>关于URL尾部的<code>/</code>有三点也需要说明一下。第一点与location配置有关，其他两点无关。</p>
<ul>
<li><p>location配置中的字符有没有<code>/</code>都没有影响(只是location, 不是alias)。也就是说<code>/user/</code>和<code>/user</code>是一样的。</p>
</li>
<li><p>如果URL结构是<code>https://domain.com/</code>的形式，尾部有没有<code>/</code>都不会造成重定向。因为浏览器在发起请求的时候，默认加上了<code>/</code>。虽然很多浏览器在地址栏里也不会显示<code>/</code>。这一点，可以访问<a href="https://www.baidu.com/" target="_blank" rel="noopener">baidu</a>验证一下。</p>
</li>
<li><p>如果URL的结构是<code>https://domain.com/some-dir/</code>。尾部如果缺少<code>/</code>将导致重定向。因为根据约定，URL尾部的<code>/</code>表示目录，没有<code>/</code>表示文件。</p>
<p>所以访问<code>/some-dir/</code>时，服务器会自动去该目录下找对应的默认文件。如果访问<code>/some-dir</code>的话，服务器会先去找<code>some-dir</code>文件，找不到的话会将<code>some-dir</code>当成目录，重定向到<code>/some-dir/</code>，去该目录下找默认文件。</p>
</li>
</ul>
<h3 id="2-rewirte规则"><a href="#2-rewirte规则" class="headerlink" title="2. rewirte规则"></a>2. rewirte规则</h3><h5 id="2-1-return指令"><a href="#2-1-return指令" class="headerlink" title="2.1 return指令"></a>2.1 return指令</h5><p>return指令写在server和location里面</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">return</span> code [text];</span><br><span class="line"><span class="attribute">return</span> code URL;</span><br><span class="line"><span class="attribute">return</span> URL;</span><br></pre></td></tr></table></figure>

<p>我们来看下面这个例子</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">return</span> <span class="number">301</span> <span class="variable">$scheme</span>://www.baidu.com<span class="variable">$request_uri</span>;</span><br></pre></td></tr></table></figure>

<p>return 指令告诉 nginx 停止处理请求, 直接返回301代码和指定重写过的URL到客户端. $scheme是指协议(http),$request_uri指包含参数的完整URI </p>
<p>对于 3xx 系列响应码, url参数就是重写的url</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">return</span> (<span class="number">301</span> | <span class="number">302</span> | <span class="number">303</span> | <span class="number">307</span>) url;</span><br></pre></td></tr></table></figure>

<p>对于其他响应吗, 可以出现一个字符串</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">return</span> (1xx | 2xx | 4xx | 5xx)[<span class="string">"text"</span>]</span><br></pre></td></tr></table></figure>

<p>例如:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">return</span> <span class="number">401</span> <span class="string">"Access denied because token is expired or invalid"</span>;</span><br></pre></td></tr></table></figure>

<h5 id="2-2-rewrite指令"><a href="#2-2-rewrite指令" class="headerlink" title="2.2 rewrite指令"></a>2.2 rewrite指令</h5><p>rewrite指令写在server和location里面, 规则会改变部分或整个用户的URL.</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">rewrite</span> regex URL [flag]</span><br></pre></td></tr></table></figure>

<ol>
<li><p>regex 正则表达式</p>
</li>
<li><p>flag</p>
<ul>
<li><p>last</p>
<p>停止当前这个请求，并根据rewrite匹配的规则重新发起一个请求。新请求又从第一阶段开始执行, 找寻新的location</p>
</li>
<li><p>break</p>
<p>break并不会重新发起一个请求，只是跳过当前的rewrite阶段，并执行本请求后续的执行阶段, 在同一个location里处理</p>
</li>
<li><p>redirect</p>
<p>返回包含302的临时重定向</p>
</li>
<li><p>permanent</p>
<p>返回包含301的永久重定向</p>
</li>
</ul>
</li>
<li><p>rewrite只能返回301或302, 如果有其他,需要后面加上return, 例如:</p>
</li>
</ol>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">rewrite</span><span class="regexp"> ^(/download/.*)/media/(\w+)\.?.*$</span> <span class="variable">$1</span>/mp3/<span class="variable">$2</span>.mp3 <span class="literal">last</span>;</span><br><span class="line"><span class="attribute">rewrite</span><span class="regexp"> ^(/download/.*)/audio/(\w+)\.?.*$</span> <span class="variable">$1</span>/mp3/<span class="variable">$2</span>.ra  <span class="literal">last</span>;</span><br><span class="line"><span class="attribute">return</span>  <span class="number">403</span>;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>匹配/download开头的URL,  然后替换相关路径</p>
</li>
<li><p><code>/download/cdn-west/media/file1</code> -&gt; <code>/download/cdn-west/mp3/file1.mp3</code></p>
</li>
<li><p>如果匹配不上, 将返回客户端403</p>
</li>
</ul>
<h5 id="2-3-try-files"><a href="#2-3-try-files" class="headerlink" title="2.3 try_files"></a>2.3 try_files</h5><p>try_files指令写在server和location里面.</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">ry_files</span> file ... uri 或 try_files file ... = code</span><br></pre></td></tr></table></figure>

<p>try_files 指令的参数是一个或多个文件或目录的列表, 以及后面的uri参数. nginx会按照顺序检查文件或目录是否存在, 并用找到的第一个文件提供服务. 如果都不存在, 内部重定向到最后的这个uri</p>
<p>例如:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span> /images/ &#123;</span><br><span class="line">    <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ /images/default.gif;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="attribute">location</span> = /images/default.gif &#123;</span><br><span class="line">    <span class="attribute">expires</span> <span class="number">30s</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>try_files常用的变量:</p>
<ul>
<li><p>$uri 表示域名以后的部分</p>
</li>
<li><p>$args  请求url中 ? 后面的参数 (不包括?本身)</p>
</li>
<li><p>$is_args  判断$args是否为空</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ /index.php<span class="variable">$is_args</span><span class="variable">$args</span>; <span class="comment">#这样就能避免多余的?号</span></span><br></pre></td></tr></table></figure>


</li>
</ul>
<ul>
<li><p>$query_string 和 $args相同</p>
</li>
<li><p>$document_root root指令指定的值</p>
</li>
<li><p>$request_filename 请求的文件路径</p>
</li>
<li><p>$request_uri 原始请求uri  </p>
</li>
</ul>
<p>我们看个例子:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">try_files</span> /app/cache/ <span class="variable">$uri</span> <span class="variable">@fallback</span>; </span><br><span class="line"><span class="attribute">index</span> index.php index.html;</span><br></pre></td></tr></table></figure>

<p>它将检测$document_root/app/cache/index.php,$document_root/app/cache/index.html 和 $document_root$uri是否存在，如果不存在着内部重定向到@fallback(＠表示配置文件中预定义标记点) 。</p>
<p>你也可以使用一个文件或者状态码(=404)作为最后一个参数，如果是最后一个参数是文件，那么这个文件必须存在。</p>
<p>我们来看一个错误:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span> ~.*\.(gif|jpg|jpeg|png)$ &#123;</span><br><span class="line">        <span class="attribute">root</span> /web/wwwroot;</span><br><span class="line">        <span class="attribute">try_files</span> /static/<span class="variable">$uri</span> <span class="variable">$uri</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>原意图是访问<code>http://example.com/test.jpg</code>时先去检查<code>/web/wwwroot/static/test.jpg</code>是否存在，不存在就取<code>/web/wwwroot/test.jpg</code></p>
<p>但由于最后一个参数是一个内部重定向，所以并不会检查<code>/web/wwwroot/test.jpg</code>是否存在，只要第一个路径不存在就会重新向然后再进入这个location造成死循环。结果出现500 Internal Server Error</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">location</span> ~.*\.(gif|jpg|jpeg|png)$ &#123;</span><br><span class="line">        <span class="attribute">root</span> /web/wwwroot;</span><br><span class="line">        <span class="attribute">try_files</span> /static/<span class="variable">$uri</span> <span class="variable">$uri</span> <span class="number">404</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样才会先检查<code>/web/wwwroot/static/test.jpg</code>是否存在，不存在就取<code>/web/wwwroot/test.jpg</code>再不存在则返回404 not found</p>
<h5 id="2-4-if指令"><a href="#2-4-if指令" class="headerlink" title="2.4 if指令"></a>2.4 if指令</h5><p>if不是系统级的指令, 是和rewrite配合的. if 必须写在server和location里面.</p>
<ul>
<li>变量名:   如果是空字符串或”0”为FALSE</li>
<li>= 判断相等, != 判断不相等</li>
<li>~ 和 ~*(不分区大小写) 将变量与正则匹配, 捕获可以用 $1 到 $9</li>
<li>!~ 和 !~* 用作不匹配运算符</li>
<li>正则含有 } 或 ; 字符需要用引号括起来</li>
<li>常用判断指令<ul>
<li>-f 和 !-f 判断是否存在文件(file)</li>
<li>-d 和 !-d 判断是否存在目录(directory)</li>
<li>-e 和 !-e 判断是否存在文件或目录(exists)</li>
<li>-x 和 !-x 判断文件是否可执行(execute)</li>
</ul>
</li>
</ul>
<p>例如下面的列子:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">if</span> (<span class="variable">$http_user_agent</span> <span class="regexp">~ Chrome)</span> &#123;</span><br><span class="line">    <span class="attribute">rewrite</span><span class="regexp"> ^([^/]*)$</span> /chrome<span class="variable">$1</span> <span class="literal">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="attribute">if</span> (<span class="variable">$request_method</span> = POST)&#123;</span><br><span class="line">    <span class="attribute">return</span> <span class="number">405</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="attribute">if</span> (-f <span class="variable">$request_filename</span>) &#123;</span><br><span class="line">    <span class="attribute">expires</span> max;</span><br><span class="line">    break;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="3-proxy-pass模块"><a href="#3-proxy-pass模块" class="headerlink" title="3. proxy_pass模块"></a>3. proxy_pass模块</h3><p>proxy_pass指令是将请求反向代理到URL参数指定的服务器上，URL可以是主机名或者IP地址+端口号的形式，例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">proxy_pass http://proxy_server;</span><br><span class="line">proxy_pass http://192.168.9.2:8000;</span><br><span class="line">proxy_pass https://192.168.9.2:8000;</span><br></pre></td></tr></table></figure>

<p>proxy_pass模块基本配置： </p>
<ul>
<li>proxy_set_header：设置服务器获取用户的主机名或者真实ip地址，以及代理者的真实ip地址。 </li>
<li>client_body_buffer_size：用于指定客户端请求主体缓冲区大小，可以理解为先保存到本地再传给用户 </li>
<li>proxy_connect_timeout：表示连接服务器的超时时间，即发起tcp握手等候响应的超时时间 </li>
<li>proxy_send_time：服务器的数据传回时间，在规定时间内服务器必须传回完所有数据，否则，nginx将断开这个连接 </li>
<li>proxy_read_time：设置nginx从代理的后端服务器获取数据的时间，表示连接建立成功后，+ nginx等待服务器的响应时间，其实是nginx已经进入服务器的排队中等候处理的时间。 </li>
<li>proxy_buffer_size：设置缓冲区大小，默认该缓冲区大小等于proxy_buffers设置的大小 </li>
<li>proxy_buffers：设置缓冲区的数量和大小，nginx从代理的服务器获取响应数据会放置到缓冲区 </li>
<li>proxy_busy_buffers_size：用于设置系统很忙时可以使用的proxy_buffers大小，官方推荐大小为proxy_buffers*2 </li>
<li>proxy_temp_file_write_size：指定proxy缓存临时文件的大小</li>
</ul>
<h5 id="3-1-proxy-set-header"><a href="#3-1-proxy-set-header" class="headerlink" title="3.1 proxy_set_header"></a>3.1 proxy_set_header</h5><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">语法:    proxy_set_header field value;</span><br><span class="line">默认值:    </span><br><span class="line">proxy_set_header Host <span class="variable">$proxy_host</span>; <span class="comment"># 注意这个是proxy_host</span></span><br><span class="line">proxy_set_header Connection close;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">上下文:    http, server, location</span><br></pre></td></tr></table></figure>

<p>允许重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。 当且仅当当前配置级别中没有定义proxy_set_header指令时，会从上面的级别继承配置。默认情况下，只有两个请求头会被重新定义：</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">proxy_set_header</span> Host       <span class="variable">$proxy_host</span>;</span><br><span class="line"><span class="attribute">proxy_set_header</span> Connection close;</span><br></pre></td></tr></table></figure>

<p>proxy_set_header也可以自定义参数，如：proxy_set_header test paroxy_test;</p>
<p>如果想要支持下划线的话，需要增加如下配置：<code>underscores_in_headers on</code>; </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">语法：underscores_in_headers on|off</span><br><span class="line">默认值：off</span><br><span class="line">使用字段：http, server</span><br><span class="line">是否允许在header的字段中带下划线</span><br></pre></td></tr></table></figure>

<h5 id="3-2-遇到的问题"><a href="#3-2-遇到的问题" class="headerlink" title="3.2 遇到的问题"></a>3.2 遇到的问题</h5><blockquote>
<p>经过反向代理后，由于在客户端和web服务器之间增加了中间层，因此web服务器无法直接拿到客户端的ip, 通过$remote_addr变量拿到的将是反向代理服务器的ip地址. 如果我们想要在web端获得用户的真实ip，就必须在nginx这里作一个赋值操作，如下：</p>
</blockquote>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">proxy_set_header</span>            X-real-ip <span class="variable">$remote_addr</span>;</span><br></pre></td></tr></table></figure>

<p>其中这个X-real-ip是一个自定义的变量名，名字可以随意取，这样做完之后，用户的真实ip就被放在X-real-ip这个变量里了，然后，在web端可以这样获取：request.getAttribute(“X-real-ip”)</p>
<blockquote>
<p> 通常我们会看到有这样一些配置:</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">        server_name liuwei.fhyx.com;</span><br><span class="line"></span><br><span class="line">        proxy_set_header       X-Real-IP $remote_addr;</span><br><span class="line">        proxy_set_header       X-Forwarded-For $proxy_add_x_forwarded_for;</span><br><span class="line">        proxy_set_header       Host $http_host;</span><br><span class="line">        proxy_redirect         off;</span><br><span class="line">        proxy_http_version     1.1;</span><br><span class="line">        proxy_set_header       Upgrade $http_upgrade;</span><br><span class="line">        proxy_set_header       Connection &quot;upgrade&quot;;</span><br><span class="line">        proxy_buffering        off;</span><br><span class="line"></span><br><span class="line">        location / &#123;</span><br><span class="line">                proxy_pass     http://127.0.0.1:8000;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        location ~ &quot;/(box|c|bub)/&quot; &#123;</span><br><span class="line">                proxy_pass     http://127.0.0.1:8081;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        location ~ /(a|o2)/ &#123;</span><br><span class="line">                proxy_pass     http://127.0.0.1:3010;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        location ~ &quot;/api/(v\d&#123;1,2&#125;)/&quot; &#123;</span><br><span class="line">                proxy_pass     http://127.0.0.1:5010;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="proxy-set-header-X-real-ip-remote-addr"><a href="#proxy-set-header-X-real-ip-remote-addr" class="headerlink" title="proxy_set_header   X-real-ip $remote_addr;"></a>proxy_set_header   X-real-ip $remote_addr;</h5><p>这句话之前已经解释过，有了这句就可以在web服务器端获得用户的真实ip, 但是，实际上要获得用户的真实ip，不是只有这一个方法。</p>
<h5 id="proxy-set-header-X-Forwarded-For-proxy-add-x-forwarded-for"><a href="#proxy-set-header-X-Forwarded-For-proxy-add-x-forwarded-for" class="headerlink" title="proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;"></a>proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;</h5><p>X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1（RFC 2616）协议并没有对它的定义，它最开始是由 Squid 这个缓存代理软件引入，用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准，被各大 HTTP 代理、负载均衡等转发服务广泛使用，并被写入 <a href="http://tools.ietf.org/html/rfc7239" target="_blank" rel="noopener">RFC 7239</a>（Forwarded HTTP Extension）标准之中。</p>
<p>X-Forwarded-For 请求头格式非常简单，就这样：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">X-Forwarded-For: client, proxy1, proxy2</span><br></pre></td></tr></table></figure>

<p>可以看到，XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成，最开始的是离服务端最远的设备 IP，然后是每一级代理设备的 IP。</p>
<p> 如果一个 HTTP 请求到达服务器之前，经过了三个代理 Proxy1、Proxy2、Proxy3，IP 分别为 IP1、IP2、IP3，用户真实 IP 为 IP0，那么按照 XFF 标准，服务端最终会收到以下信息：</p>
  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">X-Forwarded-For: IP0, IP1, IP2</span><br></pre></td></tr></table></figure>

<p>Proxy3 直连服务器，它会给 XFF 追加 IP2，表示它是在帮 Proxy2 转发请求。列表中并没有 IP3，IP3 可以在服务端通过 Remote Address 字段获得。我们知道 HTTP 连接基于 TCP 连接，HTTP 协议中没有 IP 的概念，Remote Address 来自 TCP 连接，表示与服务端建立 TCP 连接的设备 IP，在这个例子里就是 IP3。</p>
<p>Remote Address 无法伪造，因为建立 TCP 连接需要三次握手，如果伪造了源 IP，无法建立 TCP 连接，更不会有后面的 HTTP 请求。不同语言获取 Remote Address 的方式不一样，例如 php 是 <code>$_SERVER[&quot;REMOTE_ADDR&quot;]</code>，Node.js 是 <code>req.connection.remoteAddress</code>，但原理都一样。</p>
<p>对于 Web 应用来说，<code>X-Forwarded-For</code> 和 <code>X-Real-IP</code> 就是两个普通的请求头，自然就不做任何处理原样输出了。这说明，对于直连部署方式，除了从 TCP 连接中得到的 Remote Address 之外，请求头中携带的 IP 信息都不能信。  </p>
<h5 id="proxy-set-header-Host-http-host"><a href="#proxy-set-header-Host-http-host" class="headerlink" title="proxy_set_header       Host $http_host;"></a>proxy_set_header       Host $http_host;</h5><ul>
<li><p>$host：请求中的主机头(HOST)字段，如果请求中的主机头不可用或者空，则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写，不包含端口!!!!</p>
</li>
<li><p>如果客户端发过来的请求的header中有’HOST’这个字段时，<code>$http_host</code>和<code>$host</code>都是原始的’HOST’字段比如请求的时候HOST的值是<a href="http://www.csdn.net" target="_blank" rel="noopener">www.csdn.net</a> 那么反代后还是<a href="http://www.csdn.net" target="_blank" rel="noopener">www.csdn.net</a></p>
<p>如果客户端发过来的请求的header中没有有’HOST’这个字段时， 建议使用$host，这表示请求中的server name。</p>
</li>
</ul>
<h3 id="4-websocket反向代理"><a href="#4-websocket反向代理" class="headerlink" title="4. websocket反向代理"></a>4. websocket反向代理</h3><ul>
<li><p>nginx 首先确认版本必须是1.3以上。</p>
</li>
<li><p>map指令的作用： 该作用主要是根据客户端请求中$http_upgrade的值，来构造改变$connection_upgrade的值，即根据变量$http_upgrade的值创建新的变量$connection_upgrade， 创建的规则就是{}里面的东西。其中的规则没有做匹配，因此使用默认的，即 $connection_upgrade的值会一直是 upgrade。然后如果 $http_upgrade为空字符串的话， 那值会是 close。</p>
</li>
</ul>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#必须添加的</span></span><br><span class="line"><span class="attribute">map</span> <span class="variable">$http_upgrade</span> <span class="variable">$connection_upgrade</span> &#123;</span><br><span class="line">        <span class="attribute">default</span> upgrade;</span><br><span class="line">        '' close;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">#监听websocket</span></span><br><span class="line"><span class="attribute">upstream</span> websocket &#123;</span><br><span class="line">    <span class="comment">#ip_hash;</span></span><br><span class="line">    <span class="comment">#转发到服务器上相应的ws端口</span></span><br><span class="line">    <span class="attribute">server</span> localhost:<span class="number">3344</span>;</span><br><span class="line">    <span class="comment">#server localhost:8011;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_name</span> schoolsocket.zhuzhida.vip;</span><br><span class="line">    <span class="attribute">location</span> / &#123;</span><br><span class="line">        <span class="comment">#转发到http://websocket</span></span><br><span class="line">        <span class="attribute">proxy_pass</span> http://websocket;</span><br><span class="line">        <span class="attribute">proxy_read_timeout</span> <span class="number">300s</span>;</span><br><span class="line">        <span class="attribute">proxy_send_timeout</span> <span class="number">300s</span>;</span><br><span class="line"></span><br><span class="line">        <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        <span class="comment">#升级http1.1到 websocket协议  </span></span><br><span class="line">        <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Upgrade <span class="variable">$http_upgrade</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Connection  <span class="variable">$connection_upgrade</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="5-参考资料"><a href="#5-参考资料" class="headerlink" title="5. 参考资料:"></a>5. 参考资料:</h3><ul>
<li><a href="https://nginx.org/en/docs/" target="_blank" rel="noopener">https://nginx.org/en/docs/</a></li>
<li><a href="https://www.xiebruce.top/710.html" target="_blank" rel="noopener">Nginx配置location、if以及return、rewrite和 try_files 指令</a></li>
<li><a href="https://blog.csdn.net/kikajack/article/details/79322194" target="_blank" rel="noopener">Nginx 基本功能 - 将 Nginx 配置为 Web 服务器</a></li>
<li><a href="https://www.hi-linux.com/posts/53878.html" target="_blank" rel="noopener">Nginx 的 try_files 指令使用实例</a></li>
<li><a href="https://imququ.com/post/x-forwarded-for-header-in-http.html" target="_blank" rel="noopener">HTTP 请求头中的 X-Forwarded-For</a></li>
</ul>

    </div>

    
    
    
        
      
        <div id="reward-container">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作, 一个耿直的笑脸~</div>
  <button id="reward-button" disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
        
      
      <div style="display: inline-block">
        <img src="/images/wechatpay.jpg" alt="Levon 微信支付">
        <p>微信支付</p>
      </div>
        
      
      <div style="display: inline-block">
        <img src="/images/alipay.jpg" alt="Levon 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

      

      <footer class="post-footer">
          
            
          
          <div class="post-tags">
            
              <a href="/tags/linux/" rel="tag"># linux</a>
            
              <a href="/tags/nginx/" rel="tag"># nginx</a>
            
          </div>
        

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
              
                <a href="/p/7245bfc7.html" rel="next" title="nginx介绍和常用模块配置">
                  <i class="fa fa-chevron-left"></i> nginx介绍和常用模块配置
                </a>
              
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
              
                <a href="/p/fcd8becb.html" rel="prev" title="https协议简介,网站支持https, golang启动https">
                  https协议简介,网站支持https, golang启动https <i class="fa fa-chevron-right"></i>
                </a>
              
            </div>
          </div>
        
      </footer>
    
  </div>
  
  
  
  </article>

  </div>


          </div>
          
    
    
  <div class="comments" id="comments">
    <div id="disqus_thread">
      <noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
    </div>
  </div>
  
  

        </div>
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">
        
        
        
        
      

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-location指令"><span class="nav-number">1.</span> <span class="nav-text">1. location指令</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#1-1-location匹配uri的规则"><span class="nav-number">1.0.1.</span> <span class="nav-text">1.1 location匹配uri的规则:</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-2-location匹配uri的优先级"><span class="nav-number">1.0.2.</span> <span class="nav-text">1.2 location匹配uri的优先级:</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-3-location-测试"><span class="nav-number">1.0.3.</span> <span class="nav-text">1.3 location 测试</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-4-location-name的用法"><span class="nav-number">1.0.4.</span> <span class="nav-text">1.4 location @name的用法</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-5-root和alias的区别"><span class="nav-number">1.0.5.</span> <span class="nav-text">1.5 root和alias的区别</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-6-nginx显示目录结构"><span class="nav-number">1.0.6.</span> <span class="nav-text">1.6 nginx显示目录结构</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#1-7-URL尾部的-需不需要"><span class="nav-number">1.0.7.</span> <span class="nav-text">1.7 URL尾部的/需不需要</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-rewirte规则"><span class="nav-number">2.</span> <span class="nav-text">2. rewirte规则</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#2-1-return指令"><span class="nav-number">2.0.1.</span> <span class="nav-text">2.1 return指令</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#2-2-rewrite指令"><span class="nav-number">2.0.2.</span> <span class="nav-text">2.2 rewrite指令</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#2-3-try-files"><span class="nav-number">2.0.3.</span> <span class="nav-text">2.3 try_files</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#2-4-if指令"><span class="nav-number">2.0.4.</span> <span class="nav-text">2.4 if指令</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-proxy-pass模块"><span class="nav-number">3.</span> <span class="nav-text">3. proxy_pass模块</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#3-1-proxy-set-header"><span class="nav-number">3.0.1.</span> <span class="nav-text">3.1 proxy_set_header</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#3-2-遇到的问题"><span class="nav-number">3.0.2.</span> <span class="nav-text">3.2 遇到的问题</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#proxy-set-header-X-real-ip-remote-addr"><span class="nav-number">3.0.3.</span> <span class="nav-text">proxy_set_header   X-real-ip $remote_addr;</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#proxy-set-header-X-Forwarded-For-proxy-add-x-forwarded-for"><span class="nav-number">3.0.4.</span> <span class="nav-text">proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#proxy-set-header-Host-http-host"><span class="nav-number">3.0.5.</span> <span class="nav-text">proxy_set_header       Host $http_host;</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-websocket反向代理"><span class="nav-number">4.</span> <span class="nav-text">4. websocket反向代理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-参考资料"><span class="nav-number">5.</span> <span class="nav-text">5. 参考资料:</span></a></li></ol></div>
        
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image"
      src="/images/avatar.jpg"
      alt="Levon">
  <p class="site-author-name" itemprop="name">Levon</p>
  <div class="site-description" itemprop="description">Never Give Up</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        
          <a href="/archives/">
        
          <span class="site-state-item-count">127</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-categories">
        
          
            <a href="/categories/">
          
        
        <span class="site-state-item-count">34</span>
        <span class="site-state-item-name">分类</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-tags">
        
          
            <a href="/tags/">
          
        
        <span class="site-state-item-count">76</span>
        <span class="site-state-item-name">标签</span>
        </a>
      </div>
    
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="https://github.com/unix2dos" title="GitHub &rarr; https://github.com/unix2dos" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
    
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="mailto:levonfly@gmail.com" title="E-Mail &rarr; mailto:levonfly@gmail.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
    
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="https://twitter.com/levonfly" title="Twitter &rarr; https://twitter.com/levonfly" rel="noopener" target="_blank"><i class="fa fa-fw fa-twitter"></i>Twitter</a>
      </span>
    
      <span class="links-of-author-item">
      
      
        
      
      
        
      
        <a href="https://weibo.com/l6241425" title="Weibo &rarr; https://weibo.com/l6241425" rel="noopener" target="_blank"><i class="fa fa-fw fa-weibo"></i>Weibo</a>
      </span>
    
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Levon</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    <span title="站点总字数">507k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">7:41</span>
</div>

        












        
      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js?v=3.1.0"></script>
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script src="/js/utils.js?v=7.4.0"></script><script src="/js/motion.js?v=7.4.0"></script>
<script src="/js/schemes/pisces.js?v=7.4.0"></script>

<script src="/js/next-boot.js?v=7.4.0"></script>



  
  <script>
    (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>








  <script src="/js/local-search.js?v=7.4.0"></script>














  

  

  

<script>
  function loadCount() {
    var d = document, s = d.createElement('script');
    s.src = 'https://levonfly.disqus.com/count.js';
    s.id = 'dsq-count-scr';
    (d.head || d.body).appendChild(s);
  }
  // defer loading until the whole page loading is completed
  window.addEventListener('load', loadCount, false);
</script>
<script>
  function disqus_config() {
    this.page.url = "https://unix2dos.github.io/p/51e59d76.html";
    this.page.identifier = "p/51e59d76.html";
    this.page.title = 'nginx的location用法和rewrite规则';};
  function loadComments() {
    if (window.DISQUS) {
      DISQUS.reset({
        reload: true,
        config: disqus_config
      });
    } else {
      var d = document, s = d.createElement('script');
      s.src = 'https://levonfly.disqus.com/embed.js';
      s.setAttribute('data-timestamp', '' + +new Date());
      (d.head || d.body).appendChild(s);
    }
  }
    window.addEventListener('load', loadComments, false);
  
</script>

</body>
</html>
